#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <stdio.h>

#include <QPushButton>

#include "cfam.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    ui->SBoxPort->setEnabled( true );
    ui->BtnComPort->setText( "Open" );
    ui->GrpUtilities->setEnabled( false );

    //
    btn_mapper = new QSignalMapper();
    QObject::connect( btn_mapper , SIGNAL(mapped(int)), this, SLOT(map_btn_clicked(int)));
}

MainWindow::~MainWindow()
{
    int loop;

    for( loop=0; loop<modules.size(); loop++ )
    {
        delete modules.at(loop);
    }

    delete btn_mapper;
    delete ui;
}

void MainWindow::on_BtnComPort_clicked()
{
    // verifie le nom
    if( ui->BtnComPort->text() == "Open" )
    {
        // bouton de connection a l'uart
        char com_port[16U];

        sprintf(com_port,"\\\\.\\COM%d",ui->SBoxPort->value());

        if( true == uart.Open( com_port, 38400, 8, 0, 0, E_PROTOCOL_ASCII ) )
        {
            // met a jour l'ihm
            ui->SBoxPort->setEnabled( false );
            ui->BtnComPort->setText( "Close" );
            ui->GrpUtilities->setEnabled( true );

            // connexion du signal
            QObject::connect( &uart , SIGNAL(SignalAddMsg()), this, SLOT(received_msg()));
        }
    }
    else
    {
        uart.Close();

        // met a jour l'ihm
        ui->SBoxPort->setEnabled( true );
        ui->BtnComPort->setText( "Open" );
        ui->GrpUtilities->setEnabled( false );
    }
}

// definition des colone de la liste de modules present
#define COL_ADDR        0
#define COL_LQI         1
#define COL_RSSI        2
#define COL_TYPE        3
#define COL_MORE        4


void MainWindow::received_msg( void )
{
    // la on sait que l'on a recu un message, on va le lire pour l'afficher
    QList<unsigned char> msg = this->uart.GetMsg();
    QString str;
    QString tmp_str;
    unsigned char loop;


    // fenetre de debug
    for( loop=0; loop<msg.size(); loop++ )
    {
        tmp_str.clear();
        tmp_str = QString::number(msg.value(loop), 16 ).toUpper();
        if( (tmp_str.size()%2) != 0 )
        {
            tmp_str.insert( 0, "0");
        }
        str.append( tmp_str + " " );
    }
    ui->TxtInMsg->append(str);


    // analyse sommaire de la trame
    // on recup l'addresse source et on regarde si on l'a deja affichee
    if( msg.size() >= 7 )
    {
        bool l_flag = false;
        unsigned short l_src_addr = msg.value(2) + (msg.value(3)<<8);
        tmp_str.clear();
        tmp_str = QString::number(l_src_addr, 16 ).toUpper();
        if( (tmp_str.size()%2) != 0 )
        {
            tmp_str.insert( 0, "0");
        }

        for(loop=0; loop<ui->LstMod->rowCount(); loop++)
        {
            if( ui->LstMod->item(loop,COL_ADDR)->text() == tmp_str )
            {
                // on appel la fenetre associee pour refraichir les informations

                // on rafraichit les donnee du tableau
                ui->LstMod->item(loop,COL_LQI)->setText(QString::number(msg.value(0), 16 ).toUpper());
                ui->LstMod->item(loop,COL_RSSI)->setText(QString::number(msg.value(1), 16 ).toUpper());

                // regarde si il ne s'agit pas d'une trame ACK pour avoir le type du device
                if( (msg.value(4) == E_FAM_NONE) &&
                    (msg.value(5) == FAM_NONE_CMD_ACK_ID) &&
                    (msg.value(6) == FAM_NONE_CMD_ACK_PAYLOAD_SIZE) // payload length
                  )
                {
                    tmp_str.clear();

                    tmp_str = CFam::getAppName( msg.value(7) );

                    ui->LstMod->item(loop,COL_TYPE)->setText(tmp_str);
                }

                dispatch_msg( loop, &msg );

                // on sort de la boucle
                loop = ui->LstMod->rowCount();
                l_flag = true;
            }
        }

        if( false == l_flag )
        {
            int l_insert_row = ui->LstMod->rowCount();
            // on insere le nouveau venu
            QTableWidgetItem *l_new_item = new QTableWidgetItem(tmp_str);
            ui->LstMod->setRowCount(ui->LstMod->rowCount()+1);
            ui->LstMod->setItem(l_insert_row, COL_ADDR, l_new_item);
            l_new_item = new QTableWidgetItem(QString::number(msg.value(0), 16 ).toUpper());
            ui->LstMod->setItem(l_insert_row, COL_LQI, l_new_item);
            l_new_item = new QTableWidgetItem(QString::number(msg.value(1), 16 ).toUpper());
            ui->LstMod->setItem(l_insert_row, COL_RSSI, l_new_item);
            l_new_item = new QTableWidgetItem("Inconnu");
            ui->LstMod->setItem(l_insert_row, COL_TYPE, l_new_item);
            on_BtnGetId_clicked();

            QPushButton *l_new_button = new QPushButton("more...");
            QObject::connect(l_new_button, SIGNAL(clicked()), btn_mapper, SLOT(map()));
            btn_mapper->setMapping(l_new_button,l_insert_row);
            ui->LstMod->setCellWidget(l_insert_row, COL_MORE, l_new_button);

            CBaseModule *l_new_module = new CBaseModule(l_insert_row, tmp_str, this);
            modules.append(l_new_module);
            dispatch_msg( l_insert_row, &msg );
        }
    }
}

void MainWindow::on_BtnGetId_clicked()
{
    // on envoi la commande
    sendMsg( RF_BRD_ADDR, E_FAM_NONE, FAM_NONE_CMD_GET_APP_ID,
                             FAM_NONE_CMD_GET_APP_PAYLOAD_SIZE, NULL );
}

void MainWindow::sendMsg( unsigned short i_dest_addr, unsigned char i_fam_id, unsigned char i_cmd_id,
                unsigned char i_len, unsigned char *ip_payload )
{
    // on envoi la commande
    TFMsg l_msg;

    l_msg = CFam::formatMsg( i_dest_addr, i_fam_id, i_cmd_id, i_len, ip_payload );

    uart.Write( l_msg.msg, l_msg.size );
}


void MainWindow::on_BtnClearWindows_clicked()
{
    // utilitaire pour effacer les fenetres
    int loop;

    ui->TxtInMsg->clear();
    do
    {
        btn_mapper->removeMappings( ui->LstMod->cellWidget(0,COL_MORE) );
        ui->LstMod->removeRow(0);
    }while(ui->LstMod->rowCount());

    for( loop=0; loop<modules.size(); loop++ )
    {
        delete modules.at(loop);
    }
    modules.clear();
}

void MainWindow::map_btn_clicked( int id )
{
    CBaseModule *lp_module;

    lp_module = GetModules(id);

    if( NULL != lp_module )
    {
        lp_module->setFloating(false);
        lp_module->show();
    }
}

CBaseModule *MainWindow::GetModules( int i_id )
{
    int loop;
    CBaseModule *lop_module = NULL;

    for( loop=0; loop<modules.size(); loop++ )
    {
        if( modules.at(loop)->GetId() == i_id )
        {
            lop_module = modules.at(loop);
            loop = modules.size();
        }
    }

    return lop_module;
}


void MainWindow::dispatch_msg( int i_id, QList<unsigned char> *ip_msg )
{
    CBaseModule *lp_module;

    lp_module = GetModules(i_id);

    if( NULL != lp_module )
    {
        lp_module->AddMsg( ip_msg );
    }
}
